#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h> 
#include <stdlib.h>       
#include <string.h>
#include <pthread.h>
//#include <sys/sem.h>
#include <errno.h>
#include <sys/ipc.h>
//#include <sys/msg.h>
#include <sys/timeb.h>
#include <sys/socket.h>
//#include <sys/socketvar.h>
#include <sys/select.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <semaphore.h>
#include <string.h>
#include <termios.h>
#include <linux/input.h>
#include <semaphore.h>
#include <linux/shm.h>
#include <asm/unistd.h>
#include <sys/poll.h>
#include <faac.h>

#include "common.h"
   
static faacEncHandle hEncoder  = NULL; 
static unsigned long inputSamples   = 0;
static unsigned long maxOutputBytes = 0;
static unsigned char aacPcm[8192];
static unsigned char aacBuf[8192];
static unsigned char pcmBuf[8192];
static unsigned int framecount = 0;
static unsigned int stamptime = 0;
static unsigned int pcmsize = 0; 
 
static void aacDataWork(unsigned char *pData, int aacDataSize);
static unsigned int Mix ( unsigned int Data1, unsigned int Data2 );

void audioMic(struct recvData *recvData)
{
		int nRet,i;
		unsigned int Data1;
		unsigned int Data2;
	
		if( recvData->buf[0] != 0xA2 )
				return;
				
		if( hEncoder == NULL )
		{	
				if( hEncoder = faacEncOpen(44100,2,
						  					&inputSamples,&maxOutputBytes) )
				{
						faacEncConfigurationPtr myFormat;
						myFormat = faacEncGetCurrentConfiguration(hEncoder);
						myFormat->inputFormat = FAAC_INPUT_16BIT;
						myFormat->allowMidside = 1;
						myFormat->aacObjectType = LOW;
						myFormat->mpegVersion = MPEG4;
						myFormat->outputFormat = 1;
						myFormat->useTns = 1;
						myFormat->useLfe = 0;
						myFormat->quantqual = 100;
						myFormat->bitRate=0;
						myFormat->bandWidth = 0;
						myFormat->shortctl = SHORTCTL_NORMAL;
						faacEncSetConfiguration(hEncoder, myFormat);			
				}
				else
				{
						return;
				}	
		}	
		
		memcpy(aacPcm + pcmsize, recvData->buf+15,recvData->count-15);
		
		if( GetAudioOneFrame(pcmBuf) == 0 )
		{
				for( i = 0; i < 512; i++ )
				{
						Data1 = *(unsigned short*)(aacPcm+pcmsize+i*2);
						Data2 = *(unsigned short*)(pcmBuf+i*2);
						*(unsigned short*)(aacPcm+pcmsize+i*2) = Mix(Data1,Data2);
				}
		}
		
		pcmsize += recvData->count-15;

		if( pcmsize < inputSamples * 2 ) return;			
		
		pcmsize = 0;
		
		nRet = faacEncEncode( hEncoder, (int*)aacPcm, inputSamples, aacBuf, maxOutputBytes);
		
		if( nRet <= 0 ) 
		{	
				return;
		}	
			
		aacDataWork(aacBuf, nRet);
			
			 /* 	
		char name[222];
		FILE *fout=NULL;
		sprintf(name,"/sdcard/8.aac");
		if(fout==NULL) fout = fopen(name, "ab");
	  if(fout)fwrite(aacBuf, 1, nRet, fout);
	  if(fout)fclose(fout);
	  	printf("%d,%d,nRet:%d---------%s(%d)\n",recvData->count-15,inputSamples * 2,nRet,__FILE__,__LINE__);
	
	  FILE *fout1=NULL;
		sprintf(name,"/sdcard/8.pcm");
		if(fout1==NULL) fout1 = fopen(name, "ab");
	  if(fout1)fwrite(aacPcm, 1, inputSamples * 2, fout1);
	  if(fout1)fclose(fout1);
  	
		printf("%d,%d,%d---------%s(%d)\n",recvData->count-15,inputSamples * 2,nRet,__FILE__,__LINE__);
		*/
}

static void aacDataWork(unsigned char *pData, int aacDataSize) 
{
		if(aacDataSize > 1024)
		{
				static char logBuf[60];
				sprintf(logBuf, "aacDataSize > 1024 ! aacDataSize = %d", aacDataSize);
				writeLog(logBuf, __FILE__, __LINE__);	
		}
		
		sendOneMonitorAudioData(pData, aacDataSize);
		sendOneMicroClassAudioData(pData, aacDataSize);
		
		/*char name[222];
		FILE *fout=NULL;
		sprintf(name,"/sdcard/1.aac");
		if(fout==NULL) fout = fopen(name, "ab");
	  if(fout)fwrite(pData, aacDataSize, 1, fout);
	  if(fout)fclose(fout);		*/
}

static unsigned int Mix ( unsigned int Data1, unsigned int Data2 )
{
		unsigned int result = 0;
	
		unsigned int temp1 = Data1 ^ 0x8000;
		unsigned int temp2 = Data2 ^ 0x8000;
	
		unsigned int temp = temp1 * temp2 / 0x8000;
	
		if ( ( temp1 < 0x8000 ) && ( temp2 < 0x8000 ) )
		{
			result = temp ^ 0x8000;
		}
		else
		{
			result = 2 * ( temp1 + temp2 ) - temp - 0x10000;
			result ^= 0x8000;
		}
		return result;
}
